package com.nctu.dm.fpgrowth;

import java.io.BufferedWriter;
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.Map;
import java.util.Vector;
public class FPG {
	private TransactionTable  transactionTable;
	private int mSupport;
	//private Vector<TransactionValuePair> frequentItemSet;
	BufferedWriter bw ;
	public FPG(TransactionTable T , int mSupport){
		this.transactionTable = T;
		this.mSupport = mSupport;
		this.transactionTable.Sort(mSupport);
		
		
		//this.frequentItemSet = new Vector<TransactionValuePair>();
		//__CreatFPT(transactionTable);
		//__PrintFrequentItemSet();
		try{
			this.bw = new BufferedWriter(new OutputStreamWriter(new DataOutputStream(new FileOutputStream(Common.FREQUENT_FILE))));
			__ConstructFrequentItme(transactionTable);
			bw.close();
		}catch (FileNotFoundException e) {
	        e.printStackTrace();
	    }catch (IOException e) {
	    	e.printStackTrace();
	    }	
	    
	}
	
	
	private FPT __CreatFPT(TransactionTable transactionTable){
		
		if(transactionTable.name==null) return null;
		if(Common.Debug){
			System.out.printf("===tree is establishing\n");
			System.out.printf(transactionTable.name+"\n");
			System.out.printf(transactionTable.SortedTable.entrySet().toString()+"\n");
		}
		long StartTime = System.currentTimeMillis();
		FPT fpt = new FPT();	
		
		for(TransactionValuePair p:transactionTable.Table.values()){
			if(Common.Debug){
				System.out.printf("put %s:%d into tree\n",p.trans.toString(),p.count);
			}
			fpt.addT(p);
		}
		if(Common.Debug){
			System.out.printf("===tree is established, start ConstructTransactionTableForEachItem\n");
			//fpt.HT.printhead();
		}		
		if (Common.TimeDebug > 0) System.out.printf("FPT add time = %dms\n", System.currentTimeMillis() - StartTime);
		
		
		
			//we do not need the t's contents anymore
		if (Common.Debug) System.out.printf("delete Table SortTool SortedTable\n");	
		StartTime = System.currentTimeMillis();
		transactionTable.Table.clear();
		transactionTable.SortTool.clear();
		transactionTable.SortedTable.clear();	
		transactionTable.Table = null;
		transactionTable.SortTool = null;
		transactionTable.SortedTable = null;
		if (Common.TimeDebug > 0) System.out.printf("FPT delete Table SortTool SortedTable time = %dms\n", System.currentTimeMillis() - StartTime);
		StartTime = System.currentTimeMillis();
		if(Common.Debug) System.out.printf("===ConstructTransactionTableForEachItem is done\n");
		return fpt;

	}
	
	private void __ConstructFrequentItme(TransactionTable t){
		
		FPT fpt = __CreatFPT(t);
		if(Common.Debug) System.out.printf("===__CreatFPT success\n");
		
		if(fpt==null){
			if(Common.Debug) System.out.printf("===find fis \n");	
			TransactionValuePair fi=new TransactionValuePair(t.Before.parentFrequency);
			TransactionTable Current = t;		
			while(Current.Before.name.compareTo("root")!=0){	
				if(Common.Debug) System.out.printf("===Current.Before.name = %s\n",Current.Before.name);
				Current = Current.Before;
				fi.trans.add(Current.name);				
			}
			if(Common.Debug)System.out.printf("==============\nFrequent item found!, is %s\n==============\n",fi.trans.toString());
			
			//frequentItemSet.add(fi);
			
			try{
				bw.write(fi.trans.toString()+":"+fi.count+'\n');
				bw.flush();
			}catch (FileNotFoundException e) {
		        e.printStackTrace();
		    }catch (IOException e) {
		    	e.printStackTrace();
		    }				
			//System.out.println();
		}else{
			
			TransactionTable Nulltable = new TransactionTable(null,-2);
			Nulltable.Before = t;
			__ConstructFrequentItme(Nulltable);	

			//TransactionTableForEachItem.add(Nulltable);
			long StartTime = System.currentTimeMillis();
			for(Map.Entry<String,FPT.HeadTable.HeadTableValue> e :fpt.HT.Table.entrySet()){
				if(e.getValue().frequency<Common.mSupport) System.out.println("error!!");
				int i = 0;
				if(Common.Debug){
					System.out.printf("establish for key %s\n",e.getKey());
				}
				TransactionTable tt = new TransactionTable(e.getKey(),e.getValue().frequency);
				if(Common.Debug){
					System.out.printf("new Table for key %s\n",e.getKey());
				}			
				Vector<TransactionValuePair> tvps =fpt.__GetPatterns(e.getKey());
				for(TransactionValuePair tvp: tvps){
					if(Common.Debug)	System.out.printf("pattern for %s: %s:%d\n",e.getKey(),tvp.trans.toString(),tvp.count);		
					tt.addTransaction(Integer.toString(i++),tvp);
				}
				tt.Sort(Common.mSupport);
				tt.Before = t;
				__ConstructFrequentItme(tt);	
			}
			if (Common.TimeDebug > 0) System.out.printf("FPT construct each transaction table = %dms\n", System.currentTimeMillis() - StartTime);
			//System.out.printf("delete fpt");		
			fpt.DeallocateSources();	
		}
		
	}

}
